package core

import (
	"bytes"
	"errors"
	"fmt"
	"net"
)

type Client struct {
	Conn       net.Conn
	ClientID   uint64
	MsgTaskNum uint32 //当前客户端正在处理的消息任务数量
}

func NewClient(conn net.Conn) *Client {
	return &Client{
		Conn:       conn,
		MsgTaskNum: 0,
	}
}
func (c *Client) Close() {
	c.Conn.Close()
	c.ClientID = 0
}

// 4byte+byte[]  TCPSendBytes
func (c *Client) SendBytes(data []byte) error {
	if c.Conn == nil {
		return fmt.Errorf("client not connected")
	}
	buf, err := WriteBytes(bytes.NewBuffer(nil), data)
	if err != nil {
		return err
	}
	if err1 := TcpSendBytes(c.Conn, buf); err1 != nil {
		return err1
	}
	GetCount().PackageCount++
	GetCount().PackageSize += uint64(len(buf))
	return nil
}
func (c *Client) SendTopicMsg(msg *TopicMessage) error {
	buf, err := EncodePublishMessage(msg)
	if err != nil {
		return err
	}
	if err := c.SendBytes(buf); err != nil {
		return err
	}

	return nil
}
func (c *Client) ProcessData(data []byte) error {
	switch data[0] {
	case MQ_Connect:
		msg, err := DecodeConnectMsg(data)
		if err != nil {
			return err
		}

		//验证逻辑
		result, text := GetDBCmd().ConfirmLogin(msg.UserID, msg.Password)
		var res []byte
		if result {
			//验证成功,检测ClientID是否重复登陆，如有，则踢出旧客户端
			GetBroker().CheckLogin <- &LoginClient{ClientID: msg.UserID, Conn: c.Conn}

			//发送新客户端连接信息
			c.ClientID = msg.UserID
			aes := GetDBCmd().ReadKeyValue("Message.AES128")
			res, err = EncodeConnectAckMsg(&ConnectAckMsg{UserID: msg.UserID, UserName: text, Result: 0, Error: nil, AES128: aes})
			GetLog().WriteLog(Log_Info, "Client Connect Success ClientID="+fmt.Sprintf("%d", msg.UserID)+",ClientName="+text)
		} else {
			c.ClientID = 0
			res, err = EncodeConnectAckMsg(&ConnectAckMsg{UserID: msg.UserID, UserName: "", Result: 1, Error: errors.New(text), AES128: ""})
		}

		if err == nil {
			if err := c.SendBytes(res); err != nil {
				return err
			}
		} else {
			fmt.Println("Error encoding ConnectAckMsg:", err)
		}
	case MQ_HeartBeat:
		_, err := DecodeHeartBeatMsg(data)
		if err != nil {
			fmt.Println("Error decoding HeartBeatMsg:", err)
			return err
		} else {
			//fmt.Println("HeartBeatMsg received:", msg.ClientID, msg.HeartBeatTime)
			// 处理心跳消息
			// 可以在这里更新心跳时间或其他逻辑
		}
	case MQ_Sub: //注册主题
		if c.ClientID == 0 {
			return errors.New("client login fail")
		}
		subscriber, err := DecodeSubscribeMsg(data, true)
		if err != nil {
			fmt.Println("Error decoding SubscribeMsg:", err)
			return err
		}

		//返回Ack消息
		ack := GetTopicMng().RegisterSubsMsg(c, subscriber)
		if buf, err := EncodeSubscribeAckMsg(ack); err != nil {
			return err
		} else {
			c.SendBytes(buf)
		}
	case MQ_UnSub: //注销主题
		if c.ClientID == 0 {
			return errors.New("client login fail")
		}
		subscriber, err := DecodeUnSubscribeMsg(data)
		if err != nil {
			fmt.Println("Error decoding UnSubscribeMsg:", err)
			return err
		}

		//返回Ack消息
		ack := GetTopicMng().UnRegisterSubsMsg(c, subscriber)
		if buf, err := EncodeUnSubscribeAckMsg(ack); err != nil {
			return err
		} else {
			c.SendBytes(buf)
		}
	case MQ_Pub: //接收到主题数据
		if c.ClientID == 0 {
			return errors.New("client login fail")
		}
		publishMsg, err := DecodePublishMessage(data)
		if err != nil {
			fmt.Println("Error decoding PublishMessage:", err)
			return err
		}

		// 处理发布消息逻辑
		if publishMsg.QoS == MQ_QOS_1 {
			//发送ACK消息
			if buf, err := EncodePublishAckMessage(publishMsg.MessageID); err != nil {
				return err
			} else {
				if err := c.SendBytes(buf); err != nil {
					return err
				}
			}
		}
		topic := GetTopicMng().SelectTopic(publishMsg.TopicName)
		if topic != nil {
			switch topic.Type {
			case MQ_Topic_All:
				GetBroker().PostPublishMsg(publishMsg) // 将消息发送到发布通道
			case MQ_Topic_One: //负载均衡任务处理
				GetTopic_OneUser().ProcessTopic_OneUser(topic, publishMsg)
			}
		}
	case MQ_FinishAck:
		//负载均衡，消息已消费
		c.MsgTaskNum--
		GetTopic_OneUser().ProcessFinishAckMsg(data)
	case MQ_P2P: //接收到点对点数据
		if c.ClientID == 0 {
			return errors.New("client login fail")
		}
		msg, err := DecodeP2PMessage(data)
		if err != nil {
			fmt.Println("Error decoding OneByOneMessage:", err)
			return err
		}

		if msg.QoS == MQ_QOS_1 {
			//发送ACK消息
			if buf, err := EncodeP2PAckMessage(msg.MessageID); err != nil {
				return err
			} else {
				if err := c.SendBytes(buf); err != nil {
					return err
				}
			}
		}
		GetBroker().P2PMsgChannel <- msg
	}
	return nil
}
